package com.atguigu.daijia.driver.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import com.atguigu.daijia.common.constant.SystemConstant;
import com.atguigu.daijia.common.execption.GuiguException;
import com.atguigu.daijia.common.result.ResultCodeEnum;
import com.atguigu.daijia.driver.config.CosBucketProperties;
import com.atguigu.daijia.driver.config.WxConfigProperties;
import com.atguigu.daijia.driver.mapper.DriverFaceRecognitionMapper;
import com.atguigu.daijia.driver.mapper.DriverInfoMapper;
import com.atguigu.daijia.driver.mapper.DriverSetMapper;
import com.atguigu.daijia.driver.service.DriverAccountService;
import com.atguigu.daijia.driver.service.DriverInfoService;
import com.atguigu.daijia.driver.service.DriverSetService;
import com.atguigu.daijia.model.entity.driver.DriverAccount;
import com.atguigu.daijia.model.entity.driver.DriverFaceRecognition;
import com.atguigu.daijia.model.entity.driver.DriverInfo;
import com.atguigu.daijia.model.entity.driver.DriverSet;
import com.atguigu.daijia.model.form.driver.DriverFaceModelForm;
import com.atguigu.daijia.model.form.driver.UpdateDriverAuthInfoForm;
import com.atguigu.daijia.model.vo.driver.DriverAuthInfoVo;
import com.atguigu.daijia.model.vo.driver.DriverInfoVo;
import com.atguigu.daijia.model.vo.driver.DriverLoginVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tencentcloudapi.common.AbstractModel;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.iai.v20200303.IaiClient;
import com.tencentcloudapi.iai.v20200303.models.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class DriverInfoServiceImpl extends ServiceImpl<DriverInfoMapper, DriverInfo> implements DriverInfoService {
    @Resource
    private WxMaService wxMaService;

    @Resource
    private WxConfigProperties wxConfigProperties;
    @Resource
    private DriverAccountService driverAccountService;

    @Resource
    private DriverSetService driverSetService;
    @Resource
    private CosBucketProperties cosBucketProperties;

    @Resource
    private DriverSetMapper driverSetMapper;

    @Resource
    private DriverFaceRecognitionMapper driverFaceRecognitionMapper;

    @Resource
    private DriverInfoMapper driverInfoMapper;


    @Override
    public Long login(String code) {
        // 1. 根据code 获取 openid
        String openId = null;
        try {
            openId = wxMaService.getUserService().getSessionInfo(code).getOpenid();
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }
        if (!StringUtils.hasText(openId)) {
            throw new GuiguException(ResultCodeEnum.LOGIN_MOBLE_ERROR);
        }
        // 2. 判断是否是新司机
        DriverInfo driverInfo = query().eq("wx_open_id", openId).one();
        // 3. 不是新司机直接返回
        if (!ObjectUtils.isEmpty(driverInfo)) {
            return driverInfo.getId();
        }
        // 4. 新司机 初始化信息
        // 4.1 初始化基本信息
        driverInfo = new DriverInfo();
        driverInfo.setWxOpenId(openId);
        driverInfo.setNickname("driver_" + System.currentTimeMillis());
        driverInfo.setAvatarUrl("https://img1.baidu.com/it/u=728383910,3448060628&fm=253&fmt=auto&app=120&f=JPEG?w=800&h=800");
        save(driverInfo);
        // 4.2 初始化司机账户信息
        DriverAccount driverAccount = new DriverAccount();
        driverAccount.setDriverId(driverInfo.getId());
        driverAccountService.save(driverAccount);
        // 4.3 初始化司机接单信息
        DriverSet driverSet = new DriverSet();
        driverSet.setDriverId(driverInfo.getId());
        driverSet.setOrderDistance(new BigDecimal(0));// 0：无限制
        driverSet.setAcceptDistance(new BigDecimal(SystemConstant.ACCEPT_DISTANCE));// 默认接单范围：5公里
        driverSet.setIsAutoAccept(0);// 0：否 1：是
        driverSetService.save(driverSet);
        return driverInfo.getId();
    }

    @Override
    public DriverLoginVo getDriverInfo(Long driverId) {
        // 1. 判断driverId是否是空
        if (ObjectUtils.isEmpty(driverId)) {
            throw new GuiguException(ResultCodeEnum.ACCOUNT_ERROR);
        }
        // 2. 获取driverInfo
        DriverInfo driverInfo = getById(driverId);
        if (ObjectUtils.isEmpty(driverInfo)) {
            throw new GuiguException(ResultCodeEnum.ACCOUNT_ERROR);
        }
        // 3. 属性复制 driverInfo--》driverLoginVo
        DriverLoginVo driverLoginVo = new DriverLoginVo();
        BeanUtils.copyProperties(driverInfo, driverLoginVo);
        // 4. 设置 司机是否实现了人脸识别
        driverLoginVo.setIsArchiveFace(StringUtils.hasText(driverInfo.getFaceModelId()));
        return driverLoginVo;
    }

    @Override
    public Boolean updateDriverAuthInfo(UpdateDriverAuthInfoForm updateDriverAuthInfoForm) {
        // 获取司机id
        Long driverId = updateDriverAuthInfoForm.getDriverId();

        // 修改操作
        DriverInfo driverInfo = new DriverInfo();
        driverInfo.setId(driverId);
        BeanUtils.copyProperties(updateDriverAuthInfoForm, driverInfo);

        boolean update = updateById(driverInfo);
        return update;
    }

    @Override
    public Boolean creatDriverFaceModel(DriverFaceModelForm driverFaceModelForm) {
        try {
            // 实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密
            // 代码泄露可能会导致 SecretId 和 SecretKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考，建议采用更安全的方式来使用密钥，请参见：https://cloud.tencent.com/document/product/1278/85305
            // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
            Credential cred = new Credential(cosBucketProperties.getSecretId(), cosBucketProperties.getSecretKey());
            // 实例化一个http选项，可选的，没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("iai.tencentcloudapi.com");
            // 实例化一个client选项，可选的，没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            IaiClient client = new IaiClient(cred, cosBucketProperties.getRegion(), clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象
            CreatePersonRequest req = new CreatePersonRequest();
            DriverInfo driverInfo = getById(driverFaceModelForm.getDriverId());
            // 设置相关值
            req.setGroupId(cosBucketProperties.getPersionGroupId());
            // 基本信息
            req.setPersonId(String.valueOf(driverInfo.getId()));
            req.setGender(Long.parseLong(driverInfo.getGender()));
            req.setQualityControl(4L);
            req.setUniquePersonControl(4L);
            req.setPersonName(driverInfo.getName());
            req.setImage(driverFaceModelForm.getImageBase64());
            // 返回的resp是一个CreatePersonResponse的实例，与请求对象对应
            CreatePersonResponse resp = client.CreatePerson(req);
            // 输出json格式的字符串回包
            System.out.println(AbstractModel.toJsonString(resp));
            driverInfo.setFaceModelId(resp.getFaceId());
            updateById(driverInfo);
        } catch (TencentCloudSDKException e) {
            System.out.println(e.toString());
            return false;
        }
        return true;
    }

    @Override
    public DriverAuthInfoVo getDriverAuthInfo(Long driverId) {
        DriverInfo driverInfo = getById(driverId);
        DriverAuthInfoVo driverAuthInfoVo = new DriverAuthInfoVo();
        driverAuthInfoVo.setDriverId(driverId);
        BeanUtils.copyProperties(driverInfo, driverAuthInfoVo);
        return driverAuthInfoVo;
    }

    @Override
    public DriverSet getDriverSet(Long driverId) {
        QueryWrapper<DriverSet> queryWrapper = new QueryWrapper<DriverSet>().eq("driver_id", driverId);
        DriverSet driverSet = driverSetMapper.selectOne(queryWrapper);
        if (ObjectUtils.isEmpty(driverSet)) {
            throw new GuiguException(ResultCodeEnum.DATA_ERROR);
        }
        return driverSet;
    }

    /**
     * 判断司机当日是否进行人脸识别·
     *
     * @param driverId
     * @return
     */
    @Override
    public Boolean isFaceRecognition(Long driverId) {
        HashMap<String, Object> queryMap = new HashMap<>();
        queryMap.put("driver_id", String.valueOf(driverId));
        queryMap.put("face_date", LocalDate.now());
        DriverFaceRecognition driverFaceRecognition = driverFaceRecognitionMapper.selectOne(new QueryWrapper<DriverFaceRecognition>().allEq(queryMap));
        return !ObjectUtils.isEmpty(driverFaceRecognition);
    }

    /**
     * 进行人脸识别验证
     *
     * @param driverFaceModelForm
     * @return
     */
    @Override
    public Boolean verifyDriverFace(DriverFaceModelForm driverFaceModelForm) {
        try {
            // 实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密
            // 代码泄露可能会导致 SecretId 和 SecretKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考，建议采用更安全的方式来使用密钥，请参见：https://cloud.tencent.com/document/product/1278/85305
            // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
            Credential cred = new Credential(cosBucketProperties.getSecretId(), cosBucketProperties.getSecretKey());
            // 实例化一个http选项，可选的，没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("iai.tencentcloudapi.com");
            // 实例化一个client选项，可选的，没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            IaiClient client = new IaiClient(cred, cosBucketProperties.getRegion(), clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象
            VerifyFaceRequest req = new VerifyFaceRequest();
            // 设置相关参数
            req.setImage(driverFaceModelForm.getImageBase64());
            req.setPersonId(String.valueOf(driverFaceModelForm.getDriverId()));
            // 返回的resp是一个VerifyFaceResponse的实例，与请求对象对应
            VerifyFaceResponse resp = client.VerifyFace(req);
            // 输出json格式的字符串回包
            System.out.println(AbstractModel.toJsonString(resp));

            if (!resp.getIsMatch()) {
                throw new GuiguException(ResultCodeEnum.DATA_ERROR);
            }
            //  司机 司机人脸活体检测
            Boolean isBoolean = detectLiveFace(driverFaceModelForm.getImageBase64());
            if (!isBoolean) {
                throw new GuiguException(ResultCodeEnum.DATA_ERROR);
            }
            // 司机人脸和活体检测都通过
            DriverFaceRecognition driverFaceRecognition = new DriverFaceRecognition();
            driverFaceRecognition.setDriverId(driverFaceModelForm.getDriverId());
            driverFaceRecognition.setFaceDate(new Date());
            driverFaceRecognitionMapper.insert(driverFaceRecognition);
            return true;
        } catch (TencentCloudSDKException e) {
            System.out.println(e.toString());
            return false;
        }
    }


    // 人脸静态活体检测
    private Boolean detectLiveFace(String imageBase64) {
        try {
            // 实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密
            // 代码泄露可能会导致 SecretId 和 SecretKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考，建议采用更安全的方式来使用密钥，请参见：https://cloud.tencent.com/document/product/1278/85305
            // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
            Credential cred = new Credential(cosBucketProperties.getSecretId(),
                    cosBucketProperties.getSecretKey());
            // 实例化一个http选项，可选的，没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("iai.tencentcloudapi.com");
            // 实例化一个client选项，可选的，没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            IaiClient client = new IaiClient(cred, cosBucketProperties.getRegion(),
                    clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象
            DetectLiveFaceRequest req = new DetectLiveFaceRequest();
            req.setImage(imageBase64);
            // 返回的resp是一个DetectLiveFaceResponse的实例，与请求对象对应
            DetectLiveFaceResponse resp = client.DetectLiveFace(req);
            // 输出json格式的字符串回包
            System.out.println(DetectLiveFaceResponse.toJsonString(resp));
            if (resp.getIsLiveness()) {
                return true;
            }
        } catch (TencentCloudSDKException e) {
            System.out.println(e.toString());
        }
        return false;
    }

    @Override
    public Boolean updateServiceStatus(Long driverId, Integer status) {
        DriverSet driverSet = new DriverSet();
        driverSet.setDriverId(driverId);
        driverSet.setServiceStatus(status);
        int i = driverSetMapper.update(driverSet, new QueryWrapper<DriverSet>().eq("driver_id", String.valueOf(driverId)));
        return i > 0;
    }

    @Override
    public DriverInfoVo getDriverInfoOrder(Long driverId) {
        DriverInfo driverInfo = getById(driverId);
        DriverInfoVo driverInfoVo = new DriverInfoVo();
        BeanUtils.copyProperties(driverInfo, driverInfoVo);
        // 计算司机的驾驶年龄
        int firstYear = driverInfo.getDriverLicenseIssueDate().getYear();
        int nowYear = LocalDate.now().getYear();
        int driveAge = nowYear - firstYear;
        driverInfoVo.setDriverLicenseAge(driveAge);

        return driverInfoVo;
    }
}